package net.wanglu.www.zzz.service.se.nsubj;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Pattern;

import net.wanglu.www.zzz.service._Service;
import net.wanglu.www.zzz.service.se.rcmod._RcmodTuple;
import edu.stanford.nlp.trees.EnglishGrammaticalRelations;
import edu.stanford.nlp.trees.GrammaticalRelation;
import edu.stanford.nlp.trees.Tree;
import edu.stanford.nlp.trees.TreeGraphNode;
import edu.stanford.nlp.trees.TypedDependency;
import edu.stanford.nlp.trees.tregex.TregexMatcher;
import edu.stanford.nlp.trees.tregex.TregexPattern;

public class RcmodNSubjExtracter extends _Service {

	@Override
	public Object service(Object... objects) throws Exception {
		// TODO Auto-generated method stub
		HashMap<?, ?> preprocessData = (HashMap<?, ?>) objects[0];
		TypedDependency rcmod = (TypedDependency) objects[1];
		final List<?> RcmodTupleList = (List<?>) objects[2];
		
		Tree root = (Tree) preprocessData.get("root");
		Collection<?> tdl = (Collection<?>) preprocessData.get("tdl");
		
		TypedDependency nsubj = null;
		TypedDependency aux = null;
		TypedDependency copula = null;
		for( Object obj : tdl) {
			TypedDependency TD = (TypedDependency) obj;
			GrammaticalRelation reln = TD.reln();
			if ( reln.equals(EnglishGrammaticalRelations.NOMINAL_SUBJECT) || reln.equals(EnglishGrammaticalRelations.NOMINAL_PASSIVE_SUBJECT)) {
				if ( TD.gov().toString().equals(rcmod.dep().toString())) {
					nsubj = TD;
				}
			} else if ( reln.equals(EnglishGrammaticalRelations.AUX_MODIFIER) || reln.equals(EnglishGrammaticalRelations.AUX_PASSIVE_MODIFIER)) {
				if ( TD.gov().toString().equals(rcmod.dep().toString())) {
					if ( aux == null ||  root.depth(TD.dep()) < root.depth(aux.dep())) {
						aux = TD;
					}
				}
			} else if ( reln.equals(EnglishGrammaticalRelations.COPULA)) {
				if ( TD.gov().toString().equals(rcmod.dep().toString())) {
					copula = TD;
				}
			}
		}
		
		/*
		 * 求各节点及祖先
		 */
		TreeGraphNode subj = null;
		TreeGraphNode verb = null;
		if ( nsubj == null) {//nsubj为空表示rcmod中的dep部分的动词，找不到与该动词有联系的nsubj，很有可能是省略了关系代词，导致这个动词没有nsubj
			subj = rcmod.gov();
			verb = rcmod.dep();
		} else {
			subj = nsubj.dep();
			verb = nsubj.gov();
		}

		TreeGraphNode closestAux = (aux == null ? null : aux.dep());
		TreeGraphNode cop = (copula == null ? null : copula.dep());
		/*
		 * 谓语祖先
		 */
		Tree verbAncestor = null;
		if ( verb != null) {
			sb.clear();
			sb.append("/\\bV[A-Z]+\\b/");
			sb.append(">");
			sb.append("/\\bS\\b|\\bSBAR\\b|\\bSBARQ\\b|\\bSINV\\b|\\bSQ\\b/");
			sb.append("<<");
			sb.append("(");
			sb.append("/").append(Pattern.quote(verb.label().tag())).append("/").append("<");
			sb.append("/").append(Pattern.quote(verb.label().word())).append("/");
			sb.append(")");
			TregexPattern pattern = TregexPattern.compile(sb.toString());
			TregexMatcher matcher = pattern.matcher(root);
			/*
			 * 寻找离它最近的祖先
			 */
			Tree tmp = null;
			while ( matcher.find()) {
				Tree node = matcher.getMatch();
				if ( tmp == null || node.depth() < tmp.depth()) {
					tmp = node;
				}
			}
			
			if ( tmp != null) {
				verbAncestor = tmp;
			} else {
				verbAncestor = verb;
			}
		}
		/*
		 * 主语祖先
		 */
		Tree subjectAncestor = null;
		if ( subj != null) {
			sb.clear();
			sb.append("/\\bNP\\b|\\bWHNP\\b/");
			sb.append(">");
			sb.append("/\\bS\\b|\\bSBAR\\b|\\bSBARQ\\b|\\bSINV\\b|\\bSQ\\b/");
			sb.append("<<").append("(");
			sb.append("/").append(Pattern.quote(subj.label().tag())).append("/");
			sb.append("<");
			sb.append("/").append(Pattern.quote(subj.label().word())).append("/");
			sb.append(")");
			TregexPattern pattern = TregexPattern.compile(sb.toString());
			TregexMatcher matcher = pattern.matcher(root);
			Tree tmp = null;
			while ( matcher.find()) {
				Tree node = matcher.getMatch();
				if ( tmp == null || node.depth() < tmp.depth()) {
					tmp = node;
				}
			}
			if ( tmp != null) {
				subjectAncestor = tmp;
			} else {
				subjectAncestor = subj;
			}
		}
		final TreeGraphNode faux = closestAux;
		final TreeGraphNode fcop = cop;
		final TreeGraphNode fsubj = subj;
		final Tree fsubjectAncestor = subjectAncestor;
		final TreeGraphNode fverb = verb;
		final Tree fverbAncestor = verbAncestor;
		final String frelation = rcmod.reln().getShortName();
		
		return new _NSubjTuple() {
			{
				this.setAux(faux);
				this.setCop(fcop);
				this.setSubj(fsubj);
				this.setSubjectAncestor(fsubjectAncestor);
				this.setVerb(fverb);
				this.setVerbAncestor(fverbAncestor);
				this.setRelation(frelation);				
			}
			@Override
			public Object customize() throws Exception {
				// TODO Auto-generated method stub
				for( Object obj : RcmodTupleList) {
					_RcmodTuple rt = (_RcmodTuple) obj;
					if ( rt.getVerb().toString().equals(fverb.toString())) return rt;
				}
				return null;
			}
		};
	}
}
